
package com.android.fitnesscenter.version;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;

import com.android.fitnesscenter.R;
import com.android.fitnesscenter.utils.ConfigProperties;
import com.android.fitnesscenter.utils.Loger;
import com.android.fitnesscenter.utils.PhoneStateUtil;

public class UpgradeVersionService extends Service {
    private final static int DOWNLOAD_COMPLETE = 0;
    private final static int DOWNLOAD_FAIL = 1;

    public final static String BROADCAST_ACTION = "com.android.fitnesscenter.version.UpgradeVersionService";

    private String upgradeApkUrl = null;
    private int titleId = 0;
    private UpgradeHandler updateHandler;
    private File updateDir = null;
    private File updateFile = null;
    private NotificationManager updateNotificationManager = null;
    private Notification updateNotification = null;
    private Intent updateIntent = null;
    private PendingIntent updatePendingIntent = null;
    private boolean hasStarted = false;
    private Context context;
    public static int SERVICE_ID_UPGRADE = 0;
    public static int SERVICE_ID_PUSH = 1;

    @SuppressWarnings("deprecation")
    @SuppressLint("HandlerLeak")
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        context = this;
        if (null == intent) {
            stopSelf();
            return super.onStartCommand(intent, flags, startId);
        }
        boolean hasSDCard = android.os.Environment.MEDIA_MOUNTED
                .equals(android.os.Environment.getExternalStorageState());
        if (!PhoneStateUtil.hasInternet() || !hasSDCard) {
            stopSelf();
            sendMsg2Activity(false);
            return super.onStartCommand(intent, flags, startId);
        }

        if (hasStarted) {
            return super.onStartCommand(intent, flags, startId);
        } else {
            hasStarted = true;
        }

        updateHandler = new UpgradeHandler();

        titleId = intent.getIntExtra("titleId", 0);
        upgradeApkUrl = intent.getStringExtra("upgradeApkUrl");

        String downloadDir = ConfigProperties.FILE_APK_PATH;
        updateDir = new File(Environment.getExternalStorageDirectory(), downloadDir);

        updateFile = new File(updateDir, getResources().getString(titleId) + ".apk");
        Loger.d("==upgradeApkUrl==" + upgradeApkUrl + "--downloadDir--" + downloadDir);
        if (!updateFile.exists()) {
            try {
                updateDir.mkdirs();
                updateFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
                return super.onStartCommand(intent, flags, startId);
            }
        }
        this.updateNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        this.updateNotification = new Notification();

        updateIntent = new Intent();
        updatePendingIntent = PendingIntent.getActivity(this, 0, updateIntent, 0);
        updateNotification.flags = Notification.FLAG_ONGOING_EVENT; // 设置常驻 Flag
        updateNotification.icon = R.drawable.ic_launcher;
        updateNotification.tickerText = getString(R.string.upgrade_start_download);
        updateNotification.setLatestEventInfo(this, getString(R.string.upgrade_notification_title), "0%",
                updatePendingIntent);
        updateNotificationManager.notify(SERVICE_ID_UPGRADE, updateNotification);
        new Thread(new UpdateRunnable()).start();
        return super.onStartCommand(intent, flags, startId);
    }

    @SuppressLint("HandlerLeak")
    private class UpgradeHandler extends Handler {

        @SuppressWarnings("deprecation")
        @Override
        public void handleMessage(Message msg) {
            hasStarted = false;
            switch (msg.what) {
                case DOWNLOAD_COMPLETE:
                    Loger.d("download complete");
                    Uri uri = Uri.fromFile(updateFile);
                    Intent installIntent = new Intent(Intent.ACTION_VIEW);
                    installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
                    startActivity(installIntent);
                    updateNotificationManager.cancel(0);
                    sendMsg2Activity(true);
                    stopSelf();
                    break;
                case DOWNLOAD_FAIL:
                    updateNotification.setLatestEventInfo(UpgradeVersionService.this,
                            getString(R.string.upgrade_notification_title),
                            getString(R.string.upgrade_fail_down),
                            updatePendingIntent);
                    updateNotificationManager.notify(SERVICE_ID_UPGRADE,
                            updateNotification);
                    sendMsg2Activity(false);
                    stopSelf();
                    break;
                default:
                    stopService(updateIntent);
            }
            stopSelf();
        }

    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    /**
     * @Title: downloadUpdateFile
     * @param downloadUrl
     * @param saveFile
     * @return
     * @throws Exception
     */
    @SuppressWarnings("deprecation")
    public boolean downloadUpdateFile(String downloadUrl, File saveFile)
            throws Exception {
        int downloadCount = 0;
        int currentSize = 0;
        long totalSize = 0;
        int updateTotalSize = 0;

        final int CONN_TIMEOUT = 60000;
        final int READ_TIMEOUT = 60000;

        HttpsURLConnection httpsConnection = null;
        HttpURLConnection httpConnection = null;
        InputStream is = null;
        FileOutputStream fos = null;

        try {
            URL url = new URL(downloadUrl);

            if (downloadUrl.contains("https")) {
                httpsConnection = (HttpsURLConnection) url.openConnection();
                httpsConnection
                        .setRequestProperty("User-Agent", "PacificHttpClient");
                if (currentSize > 0) {
                    httpsConnection.setRequestProperty("RANGE", "bytes="
                            + currentSize + "-");
                }
                httpsConnection.setConnectTimeout(CONN_TIMEOUT);
                httpsConnection.setReadTimeout(READ_TIMEOUT);
                updateTotalSize = httpsConnection.getContentLength();

                if (httpsConnection.getResponseCode() == 404) {
                    throw new Exception("download error 404");
                }
                is = httpsConnection.getInputStream();
            } else {
                httpConnection = (HttpURLConnection) url.openConnection();
                httpConnection
                        .setRequestProperty("User-Agent", "PacificHttpClient");
                if (currentSize > 0) {
                    httpConnection.setRequestProperty("RANGE", "bytes="
                            + currentSize + "-");
                }
                httpConnection.setConnectTimeout(CONN_TIMEOUT);
                httpConnection.setReadTimeout(READ_TIMEOUT);
                updateTotalSize = httpConnection.getContentLength();

                if (httpConnection.getResponseCode() == 404) {
                    throw new Exception("download error 404");
                }
                is = httpConnection.getInputStream();
            }
            fos = new FileOutputStream(saveFile, false);
            byte buffer[] = new byte[4096];
            int readsize = 0;

            while ((readsize = is.read(buffer)) > 0) {
                fos.write(buffer, 0, readsize);
                totalSize += readsize;

                if ((downloadCount == 0)
                        || (int) (totalSize * 100 / updateTotalSize) - 1 > downloadCount) {
                    downloadCount += 1;
                    updateNotification.setLatestEventInfo(UpgradeVersionService.this,
                            getString(R.string.upgrade_downloading),
                            (int) totalSize * 100 / updateTotalSize + "%",
                            updatePendingIntent);
                    updateNotificationManager.notify(0, updateNotification);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (httpsConnection != null) {
                httpsConnection.disconnect();
            }
            if (is != null) {
                is.close();
            }
            if (fos != null) {
                fos.close();
            }
        }
        Loger.d("updateTotalSize:" + updateTotalSize);
        Loger.d("updateTotalSizeTotoal:" + totalSize);
        if (updateTotalSize == totalSize) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 此方法用来创建文件目录，支持多层不存在的文件目录创建
     * 
     * @param file
     */
    public static void createFile(File file) {
        if (file != null) {
            createFile(file.getParentFile());
            if (!file.exists()) {
                file.mkdir();
            }
        }

    }

    class UpdateRunnable implements Runnable {
        Message message = updateHandler.obtainMessage();

        public void run() {
            if (null == upgradeApkUrl) {
                return;
            }
            message.what = DOWNLOAD_COMPLETE;
            try {
                if (!updateFile.exists()) {
                    Loger.d(updateFile.getAbsolutePath());
                    updateFile.createNewFile();
                }
                Boolean downloadOK = downloadUpdateFile(upgradeApkUrl, updateFile);
                if (downloadOK) {
                    updateHandler.sendMessage(message);
                } else {
                    message.what = DOWNLOAD_FAIL;
                    updateHandler.sendMessage(message);
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                message.what = DOWNLOAD_FAIL;
                updateHandler.sendMessage(message);
            }
        }
    }

    private void sendMsg2Activity(Boolean boolean1) {
        Intent intent = new Intent();
        intent.setAction(BROADCAST_ACTION);
        intent.putExtra("downloadDone", boolean1);
        context.sendBroadcast(intent);
    }

}
